Reactã®cloneElementã®å æ¬çãªã¬ã€ããé«åºŠãªã³ã³ããŒãã³ãæäœã®ããã®ãŠãŒã¹ã±ãŒã¹ãå©ç¹ããã¹ããã©ã¯ãã£ã¹ã解説ããŸãã
React cloneElement: èŠçŽ ã®å€æŽãšããããã£æ³šå ¥ããã¹ã¿ãŒãã
Reactéçºã®ãã€ãããã¯ãªäžçã§ã¯ãæè»ã§ä¿å®æ§ã®é«ãã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«ãã³ã³ããŒãã³ãæäœã®æè¡ãç¿åŸããããšãäžå¯æ¬ ã§ããå©çšå¯èœãªæ§ã
ãªããŒã«ã®äžã§ããReact.cloneElementã¯ãå
ã®ã³ã³ããŒãã³ãã®å®çŸ©ãçŽæ¥å€æŽããããšãªããReactèŠçŽ ãä¿®æ£ãããããã£ã泚å
¥ããããã®åŒ·åãªé¢æ°ãšããŠéç«ã£ãŠããŸãããã®ã¢ãããŒãã¯äžå€æ§ïŒimmutabilityïŒãä¿é²ããã³ãŒãã®åå©çšæ§ãé«ããŸãããã®èšäºã§ã¯ãcloneElementã®è€éãªè©³çްãæãäžãããã®ãŠãŒã¹ã±ãŒã¹ãå©ç¹ããã¹ããã©ã¯ãã£ã¹ãæ¢ããŸãã
Reactã®èŠçŽ ãšã³ã³ããŒãã³ãã®çè§£
cloneElementã«é£ã³èŸŒãåã«ãReactã®èŠçŽ ãšã³ã³ããŒãã³ãã«ã€ããŠãã£ãããšçè§£ãæ·±ããŸããããReactã«ãããŠãã³ã³ããŒãã³ãã¯UIã®åå©çšå¯èœãªéšåã§ãããããå°ãã管çããããããŒãã«åå²ã§ããŸããã³ã³ããŒãã³ãã¯é¢æ°ã³ã³ããŒãã³ããŸãã¯ã¯ã©ã¹ã³ã³ããŒãã³ãã®ããããã§ãããReactèŠçŽ ãã¬ã³ããªã³ã°ããŸãã
ReactèŠçŽ ã¯ãDOMããŒããä»ã®ã³ã³ããŒãã³ããèšè¿°ãããã¬ãŒã³ãªJavaScriptãªããžã§ã¯ãã§ããç»é¢ã«è¡šç€ºãããã¹ããã®ã®è»œéãªè¡šçŸã§ããReactèŠçŽ ã¯äžå€ã§ãããäœæåŸã«å€æŽããããšã¯ã§ããŸããããã®äžå€æ§ã¯Reactã®æ žãšãªãååã§ãããäºæž¬å¯èœãªåäœãä¿èšŒããã®ã«åœ¹ç«ã¡ãŸãã
äŸïŒ
const element = React.createElement(
'h1',
{ className: 'greeting' },
'Hello, world!'
);
ãã®ã³ãŒãã¯ãã¯ã©ã¹å "greeting" ãšããã¹ã "Hello, world!" ãæã€<h1>ã¿ã°ã衚ãReactèŠçŽ ãäœæããŸãã
React.cloneElementã®ç޹ä»
React.cloneElementã¯ãæ¢åã®ReactèŠçŽ ã«åºã¥ããŠæ°ããReactèŠçŽ ãäœæã§ãã颿°ã§ããéèŠãªéãã¯ãcloneElementã䜿çšãããšãå
ã®èŠçŽ ã«åœ±é¿ãäžããããšãªãæ°ããèŠçŽ ã®propsïŒããããã£ïŒã倿Žã§ããç¹ã§ããããã¯äžå€æ§ãç¶æããããã«äžå¯æ¬ ã§ãã
cloneElementã®æ§æã¯æ¬¡ã®ãšããã§ãã
React.cloneElement(
element,
[props],
[...children]
)
- element: ã¯ããŒã³ãããReactèŠçŽ ã
- props (ä»»æ): ã¯ããŒã³ãããèŠçŽ ã«ããŒãžãããæ°ããpropsãå«ããªããžã§ã¯ãããããã®propsã¯ãåãååã®æ¢åã®propsãäžæžãããŸãã
- children (ä»»æ): ã¯ããŒã³ãããèŠçŽ ã®æ°ããåèŠçŽ ãæäŸãããå Žåãå ã®èŠçŽ ã®åèŠçŽ ã眮ãæããŸãã
cloneElementã®ãŠãŒã¹ã±ãŒã¹
cloneElementã¯ãããã€ãã®ã·ããªãªã§ç¹ã«åœ¹ç«ã¡ãŸãã
1. åã³ã³ããŒãã³ãã®propsã®è¿œå ãŸãã¯å€æŽ
æãäžè¬çãªãŠãŒã¹ã±ãŒã¹ã®1ã€ã¯ã芪ã³ã³ããŒãã³ãããåã³ã³ããŒãã³ãã®propsã远å ãŸãã¯å€æŽããå¿ èŠãããå Žåã§ããããã¯ãåå©çšå¯èœãªã³ã³ããŒãã³ããã©ã€ãã©ãªãæ§ç¯ããéã«ç¹ã«äŸ¿å©ã§ãã
Buttonã³ã³ããŒãã³ããããã芪ã³ã³ããŒãã³ãããåçã«onClickãã³ãã©ã远å ãããã·ããªãªãèããŠã¿ãŸãããã
function Button(props) {
return ;
}
function ParentComponent() {
const handleClick = () => {
alert('Button clicked!');
};
return (
{React.cloneElement(, { onClick: handleClick })}
);
}
ãã®äŸã§ã¯ãcloneElementãButtonã³ã³ããŒãã³ãã«onClickãã³ãã©ã远å ããããã«äœ¿çšãããŠããŸãã芪ã³ã³ããŒãã³ãã¯ãButtonã³ã³ããŒãã³ãèªäœã倿Žããããšãªãããã¿ã³ã®åäœãå¶åŸ¡ããŸãã
2. å ±éã®propsãæã€ã³ã³ããŒãã³ãã®ã³ã¬ã¯ã·ã§ã³ãã¬ã³ããªã³ã°ãã
ã³ã³ããŒãã³ãã®ãªã¹ããã³ã¬ã¯ã·ã§ã³ãã¬ã³ããªã³ã°ããéãcloneElementã䜿çšããŠåã³ã³ããŒãã³ãã«å
±éã®propsãæ³šå
¥ããäžè²«æ§ã確ä¿ããŠã³ãŒãã®éè€ãæžããããšãã§ããŸãã
function ListItem(props) {
return {props.children} ;
}
function List(props) {
const items = React.Children.map(props.children, child => {
return React.cloneElement(child, { color: props.textColor });
});
return {items}
;
}
function App() {
return (
Item 1
Item 2
Item 3
);
}
ããã§ã¯ãListã³ã³ããŒãã³ãããã®åèŠçŽ ïŒListItemã³ã³ããŒãã³ãïŒãå埩åŠçããcloneElementã䜿çšããŠåListItemã«textColor propãæ³šå
¥ããŸããããã«ããããã¹ãŠã®ãªã¹ãã¢ã€ãã ãListã³ã³ããŒãã³ãã§å®çŸ©ãããåãããã¹ãè²ãæã€ããšãä¿èšŒãããŸãã
3. é«éã³ã³ããŒãã³ãïŒHOCïŒ
cloneElementã¯ãé«éã³ã³ããŒãã³ãïŒHOCïŒã®å®è£
ã«ãããŠéèŠãªåœ¹å²ãæãããŸããHOCã¯ãã³ã³ããŒãã³ããåŒæ°ãšããŠåãåããæ°ãã匷åãããã³ã³ããŒãã³ããè¿ã颿°ã§ãããããã¯ã³ãŒãã®åå©çšãšã³ã³ããŒãã³ãã®åæã®ããã®åŒ·åãªãã¿ãŒã³ã§ãã
ã³ã³ããŒãã³ãã«ãã®ã³ã°æ©èœã远å ããHOCãèããŠã¿ãŸãããã
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log('Component mounted:', WrappedComponent.name);
}
render() {
return React.cloneElement( );
}
};
}
function MyComponent(props) {
return Hello, {props.name}!;
}
const EnhancedComponent = withLogging(MyComponent);
function App() {
return ;
}
ãã®äŸã§ã¯ãwithLogging HOCãMyComponentãã©ããããã³ã³ããŒãã³ããããŠã³ãããããšãã«ã³ã³ãœãŒã«ã«ã¡ãã»ãŒãžããã°åºåããŸããcloneElementã¯ãå
ã®propsãæã€ã©ãããããã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããããã«äœ¿çšããã匷åãããã³ã³ããŒãã³ããæåŸ
ã©ããã«æ©èœããããšãä¿èšŒããŸãã
4. è€åã³ã³ããŒãã³ã
è€åã³ã³ããŒãã³ãã¯ãæé»çã«é£æºããŠç¶æ
ãšåäœãå
±æããã³ã³ããŒãã³ãã§ããcloneElementã¯ãå
±æãããç¶æ
ãã€ãã³ããã³ãã©ãåã³ã³ããŒãã³ãã«æ³šå
¥ããã®ã«åœ¹ç«ã¡ãŸãã
class Tabs extends React.Component {
constructor(props) {
super(props);
this.state = { activeTab: props.defaultActiveTab || 0 };
}
handleTabClick = (index) => {
this.setState({ activeTab: index });
};
render() {
const { activeTab } = this.state;
const children = React.Children.map(this.props.children, (child, index) => {
return React.cloneElement(child, {
isActive: index === activeTab,
onClick: () => this.handleTabClick(index),
});
});
return (
{children}
);
}
}
function Tab(props) {
return (
);
}
function App() {
return (
Tab 1
Tab 2
Tab 3
);
}
ãã®äŸã§ã¯ãTabsã³ã³ããŒãã³ããã¢ã¯ãã£ããªã¿ãã®ç¶æ
ã管çããŸããcloneElementã䜿çšããŠãisActive propãšonClickãã³ãã©ãåTabã³ã³ããŒãã³ãã«æ³šå
¥ããŸããTabã³ã³ããŒãã³ãã¯ããããã®propsã䜿çšããŠãé©åãªã¹ã¿ã€ã«ãšåäœãæã€ã¿ããã¿ã³ãã¬ã³ããªã³ã°ããŸãã
cloneElementã䜿çšããå©ç¹
- äžå€æ§:
cloneElementã¯ãå ã®èŠçŽ ã倿Žãããªãããšãä¿èšŒããäžå€æ§ãšäºæž¬å¯èœãªåäœãä¿é²ããŸãã - åå©çšæ§: ã³ã¢å®çŸ©ã倿Žããããšãªãã³ã³ããŒãã³ããä¿®æ£ã§ãããããã¢ããªã±ãŒã·ã§ã³ã®ããŸããŸãªéšåã§åå©çšãããããªããŸãã
- æè»æ§: 芪ã³ã³ããŒãã³ãããåã³ã³ããŒãã³ãã«propsãæ³šå ¥ãããã®åäœãã«ã¹ã¿ãã€ãºããæè»ãªæ¹æ³ãæäŸããŸãã
- ã³ãŒãã®æç¢ºã:
cloneElementã䜿çšããããšã§ã芪ã³ã³ããŒãã³ããšåã³ã³ããŒãã³ãã®é¢å¿äºãæç¢ºã«åé¢ã§ããããã¯ãªãŒã³ã§ä¿å®æ§ã®é«ãã³ãŒãã«ã€ãªãããŸãã
cloneElementã䜿çšããéã®ãã¹ããã©ã¯ãã£ã¹
- 泚æããŠäœ¿çšãã:
cloneElementã¯åŒ·åãªããŒã«ã§ãããæ éã«äœ¿çšããå¿ èŠããããŸãã䜿ãããããšãè€éã§çè§£ãã«ããã³ãŒãã«ãªãå¯èœæ§ããããŸãã - ä»£æ¿æ¡ãæ€èšãã:
cloneElementã䜿çšããåã«ãprop drillingãã³ã³ããã¹ããªã©ãä»ã®ã¢ãããŒããããé©åã§ãªããæ€èšããŠãã ããã - ã³ãŒããææžåãã:
cloneElementã䜿çšããç®çãã³ãŒãã«æç¢ºã«èšè¿°ããä»ã®éçºè ãããªãã®æå³ãçè§£ã§ããããã«ããŸãã - 培åºçã«ãã¹ããã: ã³ãŒããæåŸ ã©ããã«åäœããããšã確èªããããã«ã培åºçãªåäœãã¹ããäœæããŠãã ããã
é¿ããã¹ãäžè¬çãªééã
- éèŠãªpropsã®äžæžã: åã³ã³ããŒãã³ããäŸåããŠããéèŠãªpropsãäžæžãããªãããã«æ³šæããŠãã ãããããã¯äºæãã¬åäœã«ã€ãªããå¯èœæ§ããããŸãã
- åèŠçŽ ã®æž¡ãå¿ã: å
ã®èŠçŽ ã®åèŠçŽ ãä¿æããã€ãããªãããããã
cloneElementã«æž¡ãããšã確èªããŠãã ãããããããªããšãåèŠçŽ ã¯å€±ãããŸãã - äžå¿
èŠãªcloneElementã®äœ¿çš: propsãçŽæ¥æž¡ããªã©ãããåçŽãªè§£æ±ºçã§ååãªå Žåã¯ã
cloneElementã®äœ¿çšãé¿ããŠãã ããã
cloneElementã®ä»£æ¿æ¡
cloneElementã¯äŸ¿å©ãªããŒã«ã§ãããç¹å®ã®ã·ããªãªã§åæ§ã®çµæãéæã§ãã代æ¿ã¢ãããŒãããããŸãã
1. Prop Drilling
Prop drillingã¯ãã³ã³ããŒãã³ãããªãŒã®è€æ°ã®ã¬ãã«ãéããŠpropsãäžã«æž¡ãããšãå«ã¿ãŸããåé·ã«ãªãå¯èœæ§ã¯ãããŸãããçè§£ããããçŽæ¥çãªã¢ãããŒãã§ãã
2. Context API
Context APIã䜿çšãããšããã¹ãŠã®ã¬ãã«ã§æåã§propsãæž¡ãããšãªããã³ã³ããŒãã³ãããªãŒå šäœã§ç¶æ ãšããŒã¿ãå ±æã§ããŸããããã¯ãã°ããŒãã«ãªããŒã¿ãããŒããå ±æããã®ã«ç¹ã«äŸ¿å©ã§ãã
3. Render Props
Render propsã¯ãã³ã³ããŒãã³ããpropãšããŠé¢æ°ãåãåãããã®é¢æ°ã䜿çšããŠåºåãã¬ã³ããªã³ã°ãããã¿ãŒã³ã§ããããã«ãããã«ã¹ã¿ã ã®ã¬ã³ããªã³ã°ããžãã¯ãã³ã³ããŒãã³ãã«æ³šå ¥ã§ããŸãã
4. Composition
ã³ã³ããŒãã³ãã®åæã¯ãè€æ°ã®ã³ã³ããŒãã³ããçµã¿åãããŠããè€éãªUIãäœæããããšãå«ã¿ãŸããããã¯Reactã®åºæ¬çãªãã¿ãŒã³ã§ããããã°ãã°cloneElementã®ä»£æ¿ãšããŠäœ¿çšã§ããŸãã
å®äžçã®äŸãšã±ãŒã¹ã¹ã¿ãã£
cloneElementã®å®çšçãªå¿çšã説æããããã«ãããã€ãã®å®äžçã®äŸãšã±ãŒã¹ã¹ã¿ãã£ãèããŠã¿ãŸãããã
1. åå©çšå¯èœãªãã©ãŒã ã©ã€ãã©ãªã®æ§ç¯
ããªãã®çµç¹ã®ããã«åå©çšå¯èœãªãã©ãŒã ã©ã€ãã©ãªãæ§ç¯ããŠãããšæ³åããŠãã ãããããã¹ãå ¥åãããããããŠã³ããã§ãã¯ããã¯ã¹ãªã©ã®äºåã«æ§ç¯ãããäžé£ã®ãã©ãŒã ã³ã³ããŒãã³ããæäŸããããšèããŠããŸãããŸããéçºè ãã©ã€ãã©ãªèªäœã倿Žããããšãªãããããã®ã³ã³ããŒãã³ãã®åäœãã«ã¹ã¿ãã€ãºã§ããããã«ããããšèããŠããŸãã
cloneElementã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã³ãŒããããã©ãŒã ã³ã³ããŒãã³ãã«ã«ã¹ã¿ã ã®ã€ãã³ããã³ãã©ãããªããŒã·ã§ã³ããžãã¯ã泚å
¥ã§ããŸããããã«ãããéçºè
ã¯ã©ã€ãã©ãªããã©ãŒã¯ããã倿Žãããããããšãªãããã©ãŒã ã³ã³ããŒãã³ããç¹å®ã®ããŒãºã«åãããŠèª¿æŽã§ããŸãã
2. ããŒããããã€ããŒã®å®è£
ããŒããããã€ããŒã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã§äžè²«ããã«ãã¯ã¢ã³ããã£ãŒã«ãæäŸããã³ã³ããŒãã³ãã§ããéåžžãContext APIã䜿çšããŠããŒãé¢é£ã®ããŒã¿ããã®åå«ãšå ±æããŸãã
cloneElementã䜿çšããŠããã¿ã³ãããã¹ããã£ãŒã«ããªã©ã®ç¹å®ã®ã³ã³ããŒãã³ãã«ããŒãé¢é£ã®propsãæ³šå
¥ã§ããŸããããã«ãããåã
ã®å®çŸ©ã倿ŽããããšãªããçŸåšã®ããŒãã«åºã¥ããŠãããã®ã³ã³ããŒãã³ãã®å€èгãã«ã¹ã¿ãã€ãºã§ããŸãã
3. åçãªããŒãã«ã³ã³ããŒãã³ãã®äœæ
åçãªããŒãã«ã³ã³ããŒãã³ãã¯ãããŸããŸãªãœãŒã¹ããã®ããŒã¿ã衚圢åŒã§ã¬ã³ããªã³ã°ã§ããã³ã³ããŒãã³ãã§ãããã®ã³ã³ããŒãã³ãã¯ãããŸããŸãªããŒã¿æ§é ãåŠçããããŸããŸãªã¿ã€ãã®åã衚瀺ã§ããã»ã©æè»ã§ããå¿ èŠããããŸãã
cloneElementã䜿çšããŠããã©ãŒããã颿°ãã«ã¹ã¿ã ã¬ã³ãã©ãŒãªã©ãååºæã®propsãããŒãã«ã»ã«ã«æ³šå
¥ã§ããŸããããã«ãããããŒã¿ãœãŒã¹ããšã«å¥ã
ã®ããŒãã«ã³ã³ããŒãã³ããäœæããããšãªããååã®å€èгãšåäœãã«ã¹ã¿ãã€ãºã§ããŸãã
çµè«
React.cloneElementã¯ãReactéçºè
ã®ããŒã«ãããã«ããã貎éãªããŒã«ã§ããäžå€æ§ãç¶æããã³ãŒãã®åå©çšæ§ãä¿é²ããªãããReactèŠçŽ ãä¿®æ£ãããããã£ã泚å
¥ããæè»ã§åŒ·åãªæ¹æ³ãæäŸããŸãããã®ãŠãŒã¹ã±ãŒã¹ãå©ç¹ããã¹ããã©ã¯ãã£ã¹ãçè§£ããããšã§ãcloneElementãæŽ»çšããŠãããå
ç¢ã§ä¿å®æ§ãé«ããæè»ãªReactã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã
æ éã«äœ¿çšããé©åãªå Žåã«ã¯ä»£æ¿æ¡ãæ€èšããããŒã ãã³ãŒãããŒã¹ã广çã«çè§£ãç¶æã§ããããã«ã³ãŒããæç¢ºã«ææžåããããšãå¿ããªãã§ãã ããã